package service

import (
	"database/sql"
	"encoding/json"
	"errors"
	"math/rand"
	"time"
	connect "todolist-go/src/Connect"
	dao "todolist-go/src/Dao"
	utils "todolist-go/src/Utils"
	vo "todolist-go/src/Vo"

	"github.com/go-redis/redis"
)

var (
	Db *sql.DB
	Rd *redis.Client
)

func init() {
	//初始化数据库连接
	Db = connect.NewMysqlClient()
	Rd = connect.NewRedisClient()
}

func UserRegister(u *vo.RegisterParams) (utils.Result, error) {
	if u.Account == "" || u.Password == "" || u.Nickname == "" {
		return utils.NewResult().Fail(utils.PARAM_ERROR_CODE, utils.PARAM_ERROR), nil
	}
	//从数据库中查询该用户是否存在
	selectStr := "select account from td_user where account=?"
	var registerUser dao.User
	Db.QueryRow(selectStr, u.Account).Scan(&registerUser.Account)
	if registerUser.Account != "" {
		return utils.NewResult().Fail(utils.REPEAT_REGISTER_CODE, utils.REPEAT_REGISTER), nil
	}
	//到了这个地方证明该用户未被注册，将其信息保存到数据库
	//生成唯一id
	w, _ := utils.NewWorker(rand.Int63n(100))
	id := w.GetId()
	//对明文密码进行MD5加密
	dbPassword := utils.Md5(u.Password)
	insertStr := "insert into td_user(id, account, password, nickname) values (?,?,?,?)"
	_, err := Db.Exec(insertStr, id, u.Account, dbPassword, u.Nickname)
	if err != nil {
		return utils.NewResult().Fail(200, "数据插入失败"), errors.New("数据插入失败")
	}
	//根据id生成token
	token, _ := utils.CreateToken(id)
	registerUser.Id = id
	registerUser.Account = u.Account
	registerUser.Password = dbPassword
	registerUser.Nickname = u.Nickname
	v, _ := json.Marshal(registerUser)
	Rd.Set("TOKEN_"+token, string(v), time.Minute*10)
	return utils.NewResult().Success("注册成功", token), nil
}

func UserLogin(u *vo.LoginParams) utils.Result {
	//1.判断传递的参数是否为空
	if u.Account == "" || u.Password == "" {
		return utils.NewResult().Fail(utils.PARAM_ERROR_CODE, utils.PARAM_ERROR)
	}
	//2.判断账号密码是否匹配和正确
	var user dao.User
	userPw := utils.Md5(u.Password)
	queryStr := "select * from td_user where account=? and password=? limit 1"
	Db.QueryRow(queryStr, u.Account, userPw).Scan(&user.Id, &user.Account, &user.Password, &user.Nickname)
	//根据是否有这个account匹配来判断是否有该用户
	//判断是否为空结构体 (user == dao.User{}) 要加括号
	if (user == dao.User{}) {
		return utils.NewResult().Fail(utils.ACCOUNT_OR_PASSWORD_NOT_EXIST_CODE, utils.ACCOUNT_OR_PASSWORD_NOT_EXIST)
	}
	token, _ := utils.CreateToken(user.Id)
	v, _ := json.Marshal(user)
	Rd.Set("TOKEN_"+token, string(v), time.Minute*15)
	return utils.NewResult().Success("登录成功", token)
}

func GetCurrentUser(s *string) utils.Result {
	if *s == "" {
		return utils.NewResult().Fail(utils.NO_LOGIN_CODE, utils.NO_LOGIN)
	}
	i, _ := utils.ParseToken(*s)
	if i == 0 {
		return utils.NewResult().Fail(utils.NO_LOGIN_CODE, utils.NO_LOGIN)
	}
	//不是.String()
	jsonStr, _ := Rd.Get("TOKEN_" + *s).Result()
	var (
		user   dao.User
		userVo vo.UserVo
	)
	err := json.Unmarshal([]byte(jsonStr), &user)
	if err != nil {
		return *utils.NewResult()
	}
	//相同字段拷贝
	utils.StructCopy(&user, &userVo)
	return utils.NewResult().DefaultSuccess(userVo)
}

func Logout(s *string) utils.Result {
	if *s == "" {
		return utils.NewResult().Fail(utils.NO_LOGIN_CODE, utils.NO_LOGIN)
	}
	//删除redis中的token
	Rd.Del("TOKEN_" + *s)
	return utils.NewResult().Success("登出成功", nil)
}
